package rs.etf.es.algorithm;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class NodeAddressBook implements Serializable, Cloneable {

    private static NodeAddressBook statAddressBook;

    public static NodeAddressBook instance() {
	if (statAddressBook == null) {
	    statAddressBook = new NodeAddressBook();
	}

	return statAddressBook;
    }

    private HashMap<String, Node> addressBook;
    private Node root;

    private NodeAddressBook() {
	addressBook = new HashMap<String, Node>();
    }

    public void addNode(Node newNode) {
	addressBook.put(newNode.getName(), newNode);
    }

    public Node getNode(String name) {
	return addressBook.get(name);
    }

    public ArrayList<Node> getAllNodes() {
	Set<Entry<String, Node>> set = addressBook.entrySet();
	Iterator<Entry<String, Node>> iter = set.iterator();
	ArrayList<Node> resultList = new ArrayList<Node>();

	while (iter.hasNext()) {
	    Map.Entry<String, Node> entry = iter.next();
	    Node currentNode = entry.getValue();
	    resultList.add(currentNode);
	}

	return resultList;
    }

    public Node getRoot() {
	return root;
    }

    /**
     * This method adopts CPT of node to be root adding NO_PARENT and
     * NO_CONDITION maps in CPT hash map
     */
    public void setRoot(Node root) {
	this.root = root;

	if (root.getMyCPT() != null) {
	    HashMap<String, HashMap<String, Double>> newHashMap = new HashMap<String, HashMap<String, Double>>();
	    root.getMyCPT().getProbabilitiesMap().put(Node.NO_PARENT, newHashMap);

	    for (String val : root.getValues()) {
		HashMap<String, Double> map = new HashMap<String, Double>();
		root.getMyCPT().getProbabilitiesMap().get(Node.NO_PARENT).put(val, map);
	    }
	}

    }

    public void markAsRoot(Node root) {
	this.root = root;
    }

    public Node getNodeForName(String name) {
	ArrayList<Node> allNodes = getAllNodes();
	for (Node i : allNodes) {
	    if (i.getName().equals(name)) {
		return i;
	    }
	}
	return null;
    }

    public HashMap<String, Node> getAddressBook() {
	return addressBook;
    }

    public void setAddressBook(HashMap<String, Node> addressBook) {
	this.addressBook = addressBook;
    }

    public String toString() {
	String res = "";
	for (String nodeName : addressBook.keySet()) {
	    Node i = addressBook.get(nodeName);
	    res += "CPT\n";
	    res += i.getStringCPT();
	    res += "MESSAGES\n";
	    res += i.getStringLambdaPiMessages();
	    res += "VALUES\n";
	    res += i.getStringLambdaPiValues();
	    res += "PROBABILITIES\n";
	    res += i.getStringProbabilities();
	    res += "######################################\n";
	}

	return res;
    }

}
